package com.fy.paper.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.fy.core.consts.ExamContant;
import com.fy.core.consts.PaperConst;
import com.fy.core.consts.QuTypeConstant;
import com.fy.core.context.AuthContext;
import com.fy.core.enums.ApiErrorEnum;
import com.fy.core.exception.ServiceException;
import com.fy.core.vo.ApiRest;
import com.fy.exam.entity.Exam;
import com.fy.exam.entity.ExamRepo;
import com.fy.exam.mapper.ExamMapper;
import com.fy.exam.mapper.ExamRepoMapper;
import com.fy.paper.entity.Paper;
import com.fy.paper.entity.PaperQu;
import com.fy.paper.entity.PaperQuAnswer;
import com.fy.paper.mapper.PaperMapper;
import com.fy.paper.mapper.PaperQuAnswerMapper;
import com.fy.paper.mapper.PaperQuMapper;
import com.fy.paper.service.PaperService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fy.paper.vo.DtkVo;
import com.fy.qu.entity.Qu;
import com.fy.qu.entity.QuAnswer;
import com.fy.qu.mapper.QuAnswerMapper;
import com.fy.qu.mapper.QuMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 试卷 服务实现类
 * </p>
 *
 * @author hxd
 * @since 2023-06-20
 */
@Service
public class PaperServiceImpl extends ServiceImpl<PaperMapper, Paper> implements PaperService {
    @Autowired
    private ExamMapper examMapper;
    @Autowired
    private ExamRepoMapper examRepoMapper;
    @Autowired
    private QuMapper quMapper;
    @Autowired
    private PaperQuMapper paperQuMapper;
    @Autowired
    private QuAnswerMapper quAnswerMapper;
    @Autowired
    private PaperQuAnswerMapper paperQuAnswerMapper;

    private static List<String> ABC = Arrays.asList(new String[]{
            "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K","L","M","N","O","P","Q","R","S","T","U","V","W","X"
            ,"Y","Z"
    });

    @Override
    @Transactional
    public ApiRest<String> create(String examId) {
        LambdaQueryChainWrapper<Exam> examLambdaQueryChainWrapper =
                new LambdaQueryChainWrapper<>(examMapper);
        Exam exam = examLambdaQueryChainWrapper.eq(Exam::getId, examId).one();
        //如果考试为空，无法颁发试卷
        if (exam == null) {
            throw new ServiceException(ApiErrorEnum.EXAM_NOT_EXIT);
        }
        //如果限时
        if (exam.getTimeLimit() == 1) {
            Date now = new Date();
            Date startTime = exam.getStartTime();
            Date endTime = exam.getEndTime();
            if (DateUtil.compare(now, startTime) == -1) {
                throw new ServiceException(ApiErrorEnum.EXAM_NOT_TIME);
            }
            if (DateUtil.compare(now, endTime) == 1) {
                throw new ServiceException(ApiErrorEnum.EXAM_NOT_TIME);
            }
        }
        //考试是否结束
        if (exam.getState() == ExamContant.CLOSE) {
            throw new ServiceException(ApiErrorEnum.EXAM_ClOSED);
        }
        //试卷是否已经存在
        String userId = AuthContext.getUser().getUserId() + "";

        LambdaQueryChainWrapper<Paper> paperLambdaQueryChainWrapper =
                new LambdaQueryChainWrapper<>(this.baseMapper);
        Paper paper = paperLambdaQueryChainWrapper.eq(Paper::getExamId, examId)
                .eq(Paper::getUserId, userId).one();
        //试卷已存在
        if (paper != null) {
            return ApiRest.success(paper.getId());
        }

        //创建试卷
        Paper newPaper = new Paper();
        newPaper.setId(IdWorker.getIdStr());
        newPaper.setExamId(examId);
        newPaper.setUserId(userId);
        newPaper.setCreateTime(new Date());
        newPaper.setUpdateTime(new Date());
        newPaper.setDepartId(AuthContext.getUser().getDeptId() + "");

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(calendar.MINUTE, exam.getTotalTime());

        newPaper.setLimitTime(calendar.getTime());//试卷结束时间=系统当前时间+考试规定时长

        newPaper.setState(PaperConst.ING);
        newPaper.setTitle(exam.getTitle());
        newPaper.setUserScore(0);
        newPaper.setUserTime(0);
        newPaper.setTotalTime(exam.getTotalTime());
        //总分
        newPaper.setTotalScore(exam.getTotalScore());
        //主观题分数
        Map map = examMapper.totalSubScore(examId);
        BigDecimal subScore = (BigDecimal) map.get("sub_score");
        newPaper.setSubjScore(subScore.intValue());
        //客观题总分
        newPaper.setObjScore(exam.getTotalScore() - subScore.intValue());
        newPaper.setHasSaq(subScore.intValue() > 0 ? 1 : 0);
        this.baseMapper.insert(newPaper);

        //组卷
        List<Qu> paperQus = zujuan(examId);

        List<PaperQu> paperQuList = paperQus.stream().map(item -> {
            PaperQu paperQu = new PaperQu();
            paperQu.setId(IdWorker.getIdStr());
            paperQu.setPaperId(newPaper.getId());
            paperQu.setQuId(item.getId());
            paperQu.setAnswer("");//主观题答案
            paperQu.setAnswered(0);//0:未答 1：已答
            paperQu.setActualScore(0);
            paperQu.setIsRight(0);
            paperQu.setQuType(item.getQuType());
            paperQu.setScore(item.getScore());//题目分数
            return paperQu;
        }).collect(Collectors.toList());
        //题号
        int sort=0;
        for (int i = 0; i < paperQuList.size(); i++) {
            if (paperQuList.get(i).getQuType()== QuTypeConstant.RADIO){//单选题
                paperQuList.get(i).setSort(++sort);
            }
        }
        for (int i = 0; i < paperQuList.size(); i++) {
            if (paperQuList.get(i).getQuType()== QuTypeConstant.MULTI){//多选题
                paperQuList.get(i).setSort(++sort);
            }
        }
        for (int i = 0; i < paperQuList.size(); i++) {
            if (paperQuList.get(i).getQuType()== QuTypeConstant.JUDGE){//判断题
                paperQuList.get(i).setSort(++sort);
            }
        }
        for (int i = 0; i < paperQuList.size(); i++) {
            if (paperQuList.get(i).getQuType()== QuTypeConstant.JDT){//简答题
                paperQuList.get(i).setSort(++sort);
            }
        }
        paperQuList.forEach(item->{
            paperQuMapper.insert(item);
        });

        //给每道题绑定答案选项
        for (PaperQu paperQu : paperQuList) {
            String quId = paperQu.getQuId();
            //查询题目的答案选择
            QueryWrapper<QuAnswer> quAnswerQueryWrapper=new QueryWrapper<>();
            quAnswerQueryWrapper.lambda().eq(QuAnswer::getQuId,quId);
            List<QuAnswer> quAnswers = quAnswerMapper.selectList(quAnswerQueryWrapper);
            for (int i = 0; i < quAnswers.size(); i++) {
                PaperQuAnswer paperQuAnswer=new PaperQuAnswer();
                paperQuAnswer.setId(IdWorker.getIdStr());
                paperQuAnswer.setPaperId(newPaper.getId());
                paperQuAnswer.setAnswerId(quAnswers.get(i).getId());
                paperQuAnswer.setQuId(quId);
                paperQuAnswer.setIsRight(quAnswers.get(i).getIsRight());
                paperQuAnswer.setChecked(0);
                paperQuAnswer.setAbc(ABC.get(i));

                paperQuAnswerMapper.insert(paperQuAnswer);
            }
        }




        return ApiRest.success(newPaper.getId());
    }

    @Override
    public ApiRest<DtkVo> dtk(String paperId) {
        Paper paper = this.baseMapper.selectById(paperId);
        if (paper==null){
            throw new ServiceException(ApiErrorEnum.PAPER_NOT_EXIT);
        }

        if (paper.getState()==PaperConst.END){
            throw new ServiceException(ApiErrorEnum.PAPER_IS_CLOSE);
        }
        //单选题
        QueryWrapper<PaperQu> radioQuery=new QueryWrapper<>();
        radioQuery.lambda().eq(PaperQu::getPaperId,paperId)
                .eq(PaperQu::getQuType,QuTypeConstant.RADIO)
                .orderByAsc(PaperQu::getSort);
        List<PaperQu> radios = paperQuMapper.selectList(radioQuery);
        //多选题
        QueryWrapper<PaperQu> multiQuery=new QueryWrapper<>();
        multiQuery.lambda().eq(PaperQu::getPaperId,paperId)
                .eq(PaperQu::getQuType,QuTypeConstant.MULTI)
                .orderByAsc(PaperQu::getSort);
        List<PaperQu> multis = paperQuMapper.selectList(multiQuery);
        //判断题
        QueryWrapper<PaperQu> judgeQuery=new QueryWrapper<>();
        judgeQuery.lambda().eq(PaperQu::getPaperId,paperId)
                .eq(PaperQu::getQuType,QuTypeConstant.JUDGE)
                .orderByAsc(PaperQu::getSort);
        List<PaperQu> judges = paperQuMapper.selectList(judgeQuery);
        //简答题
        QueryWrapper<PaperQu> jdtQuery=new QueryWrapper<>();
        jdtQuery.lambda().eq(PaperQu::getPaperId,paperId)
                .eq(PaperQu::getQuType,QuTypeConstant.JDT)
                .orderByAsc(PaperQu::getSort);
        List<PaperQu> jdts = paperQuMapper.selectList(jdtQuery    );

        DtkVo dtkVo=new DtkVo();
        dtkVo.setRadios(radios);
        dtkVo.setMultis(multis);
        dtkVo.setJudges(judges);
        dtkVo.setJdts(jdts);

        //剩余时间=试卷结束时间-系统当前时间
        Date now=new Date();
        Date limitTime = paper.getLimitTime();
        long endTime = limitTime.getTime();
        dtkVo.setLeftSeconds((endTime-now.getTime())/1000);



        return ApiRest.success(dtkVo);
    }

    public List<Qu> zujuan(String examId){
        /*组卷：参考exam_repo*/
        QueryWrapper<ExamRepo> examRepoQueryWrapper=new QueryWrapper<>();
        examRepoQueryWrapper.lambda().eq(ExamRepo::getExamId,examId);
        List<ExamRepo> examRepos = examRepoMapper.selectList(examRepoQueryWrapper);
        List<Qu> excludes=new ArrayList<>();//避免重复题目
        List<Qu> paperQus=new ArrayList<>();
        int totalCount=0;
        for (ExamRepo examRepo : examRepos) {
            if (examRepo.getRadioCount()>0){//单选题
                totalCount+=examRepo.getRadioCount();
                //随机出题
                List<Qu> radios = quMapper.randQu(examRepo.getRepoId(), QuTypeConstant.RADIO, examRepo.getRadioCount(),excludes);
                for (Qu radio : radios) {
                    radio.setScore(examRepo.getRadioScore());
                }
                CollectionUtil.addAll(paperQus,radios);
                CollectionUtil.addAll(excludes,radios);
            }
            if (examRepo.getMultiCount()>0){//多选题
                totalCount+=examRepo.getMultiCount();
                //随机出题
                List<Qu> multis = quMapper.randQu(examRepo.getRepoId(), QuTypeConstant.MULTI, examRepo.getMultiCount(),excludes);
                for (Qu multi : multis) {
                    multi.setScore(examRepo.getMultiScore());
                }
                CollectionUtil.addAll(paperQus,multis);
                CollectionUtil.addAll(excludes,multis);
            }
            if (examRepo.getJudgeCount()>0){//判断题
                totalCount+=examRepo.getJudgeCount();
                //随机出题
                List<Qu> judes = quMapper.randQu(examRepo.getRepoId(), QuTypeConstant.JUDGE, examRepo.getJudgeCount(),excludes);
                for (Qu jude : judes) {
                    jude.setScore(examRepo.getJudgeScore());
                }
                CollectionUtil.addAll(paperQus,judes);
                CollectionUtil.addAll(excludes,judes);
            }
            if (examRepo.getJdtCount()>0){//简答题
                totalCount+=examRepo.getJdtCount();
                //随机出题
                List<Qu> jdts = quMapper.randQu(examRepo.getRepoId(), QuTypeConstant.JDT, examRepo.getJdtCount(),excludes);
                for (Qu jdt : jdts) {
                    jdt.setScore(examRepo.getJdtScore());
                }
                CollectionUtil.addAll(paperQus,jdts);
                CollectionUtil.addAll(excludes,jdts);
            }
        }
        if (paperQus.size()<totalCount){
            throw new ServiceException(ApiErrorEnum.PAPER_FAIL);
        }
        return paperQus;
    }
}
